package redis

import (
	"time"
	"context"
)

// 移出并获取列表的第一个元素， 如果列表没有元素会阻塞列表直到等待指定秒单位时间超时或发现可弹出元素为止
func (h *Handler) BLPop(timeout int64, key string) (value string, err error) {
	values := make([]string, 0)
	values, err = h.Client.BLPop(context.Background(), time.Duration(timeout)*time.Second, key).Result()
	if len(values) == 2 {
		value = values[1]
	}
	go h.Log("List-BLPop", []interface{}{timeout, key}, value, err)
	return
}

// 移出并获取列表的最后一个元素， 如果列表没有元素会阻塞列表直到等待指定秒单位时间超时或发现可弹出元素为止
func (h *Handler) BRPop(timeout int64, key string) (value string, err error) {
	values := make([]string, 0)
	values, err = h.Client.BRPop(context.Background(), time.Duration(timeout)*time.Second, key).Result()
	if len(values) == 2 {
		value = values[1]
	}
	go h.Log("List-BRPop", []interface{}{timeout, key}, value, err)
	return
}

// 从列表中弹出一个值，将弹出的元素插入到另外一个列表中并返回它； 如果列表没有元素会阻塞列表直到等待指定秒单位时间超时或发现可弹出元素为止
func (h *Handler) BRPopLPush(source, destination string, timeout int64) (value string, err error) {
	value, err = h.Client.BRPopLPush(context.Background(), source, destination, time.Duration(timeout)*time.Second).Result()
	go h.Log("List-BRPopLPush", []interface{}{source, destination, timeout}, value, err)
	return
}

// 通过索引获取列表中的元素
func (h *Handler) LIndex(key string, index int64) (value string, err error) {
	value, err = h.Client.LIndex(context.Background(), key, index).Result()
	go h.Log("List-LIndex", []interface{}{key, index}, value, err)
	return
}

// 在指定列表的元素前插入元素，返回插入元素索引值
func (h *Handler) LInsertBefore(key string, pivot, value interface{}) (index int64, err error) {
	index, err = h.Client.LInsertBefore(context.Background(), key, pivot, value).Result()
	go h.Log("List-LInsertBefore", []interface{}{key, pivot, value}, index, err)
	return
}

// 在指定列表的元素后插入元素，返回插入元素索引值
func (h *Handler) LInsertAfter(key, pivot, value string) (index int64, err error) {
	index, err = h.Client.LInsertAfter(context.Background(), key, pivot, value).Result()
	go h.Log("List-LInsertAfter", []interface{}{key, pivot, value}, index, err)
	return
}

// 获取列表长度
func (h *Handler) LLen(key string) (len int64, err error) {
	len, err = h.Client.LLen(context.Background(), key).Result()
	go h.Log("List-LLen", key, len, err)
	return
}

// 移出并获取列表的第一个元素，返回值为移除的元素
func (h *Handler) LPop(key string) (value string, err error) {
	value, err = h.Client.LPop(context.Background(), key).Result()
	go h.Log("List-LPop", key, value, err)
	return
}

// 将一个或多个值插入到列表头部
func (h *Handler) LPush(key string, values ...interface{}) (count int64, err error) {
	count, err = h.Client.LPush(context.Background(), key, values...).Result()
	go h.Log("List-LPush", []interface{}{key, values}, count, err)
	return
}

// 将一个或多个值插入到已存在的列表头部
func (h *Handler) LPushX(key string, values ...interface{}) (count int64, err error) {
	count, err = h.Client.LPushX(context.Background(), key, values...).Result()
	go h.Log("List-LPushX", []interface{}{key, values}, count, err)
	return
}

// 获取列表指定索引范围内的元素
func (h *Handler) LRange(key string, start, end int64) (values []string, err error) {
	values, err = h.Client.LRange(context.Background(), key, start, end).Result()
	go h.Log("List-LRange", []interface{}{key, start, end}, values, err)
	return
}

// 移除列表元素，根据参数 COUNT 的值，移除列表中与参数 VALUE 相等的元素
func (h *Handler) LRem(key string, count int64, value string) (index int64, err error) {
	index, err = h.Client.LRem(context.Background(), key, count, value).Result()
	go h.Log("List-LRem", []interface{}{key, count, value}, index, err)
	return
}

// 通过索引设置列表元素的值
func (h *Handler) LSet(key string, index int64, value string) (status string, err error) {
	status, err = h.Client.LSet(context.Background(), key, index, value).Result()
	go h.Log("List-LSet", []interface{}{key, index, value}, status, err)
	return
}

// 对一个列表进行修剪(trim)，就是说，让列表只保留指定区间内的元素，不在指定区间之内的元素都将被删
func (h *Handler) LTrim(key string, start, end int64) (status string, err error) {
	status, err = h.Client.LTrim(context.Background(), key, start, end).Result()
	go h.Log("List-LTrim", []interface{}{key, start, end}, status, err)
	return
}

// 移除列表的最后一个元素，返回值为移除的元素
func (h *Handler) RPop(key string) (value string, err error) {
	value, err = h.Client.RPop(context.Background(), key).Result()
	go h.Log("List-RPop", key, value, err)
	return
}

// 移除列表的最后一个元素，并将该元素添加到另一个列表并返回
func (h *Handler) RPopLPush(source, destination string) (value string, err error) {
	value, err = h.Client.RPopLPush(context.Background(), source, destination).Result()
	go h.Log("List-RPopLPush", []interface{}{source, destination}, value, err)
	return
}

// 将一个或多个值插入到列表尾部
func (h *Handler) RPush(key string, values ...interface{}) (index int64, err error) {
	index, err = h.Client.RPush(context.Background(), key, values...).Result()
	go h.Log("List-RPush", []interface{}{key, values}, index, err)
	return
}

// 将一个或多个值插入到已存在的列表尾部
func (h *Handler) RPushX(key string, values ...interface{}) (index int64, err error) {
	index, err = h.Client.RPushX(context.Background(), key, values).Result()
	go h.Log("List-RPushX", []interface{}{key, values}, index, err)
	return
}
